Remediation scripts/Enable the built-in vulnerability assessment solution on virtual machines (powered by Qualys)/PowerShell/qualys-remediate-unhealthy-vms.ps1 (52 lines of code) (raw):

<# .NOTES Author: Lior Arviv, MSFT Version: 2.0.0 Created: 01/02/2018 Updated: 14/12/2020 - Added support for Azure Arc enabled servers #> #Requires -Modules Az.Accounts, Az.ResourceGraph if (-not (Get-AzContext)) { Write-Host "Please authenticate to Azure using 'Connect-AzAccount'" } $query = @" securityresources | where type == 'microsoft.security/assessments' and name == 'ffff0522-1e88-47fc-8382-2a80ba848f5d' | extend status = properties.status.code, resourceid = properties.resourceDetails.Id | where status == 'Unhealthy' | project resourceid "@ $vms = Search-AzGraph -Query $query foreach ($vm in $vms) { # Check if the resource is a regular virtual machine or Azure Arc connected if (($vm.resourceid -split '\/')[-3] -match "Microsoft.Compute") { $vmName = ($vm.resourceid -split '\/')[-1] Write-Host "Working on $vmName" -ForegroundColor Green $vmStatus = Invoke-AzRestMethod -Path ('{0}/instanceView?api-version=2020-06-01' -f $vm.resourceid) -Method GET | Select-Object -ExpandProperty Content | ConvertFrom-Json | Select-Object -ExpandProperty Statuses if ($vmStatus.displayStatus -match 'VM running') { $res = Invoke-AzRestMethod -Path ('{0}/providers/Microsoft.Security/serverVulnerabilityAssessments/default?api-Version=2015-06-01-preview' -f $vm.resourceid) -Method PUT if ($res.StatusCode -notmatch '200|202') { Write-Host ($res.Content | ConvertFrom-Json).Error.message -ForegroundColor Red } } else { Write-Host "$vmName is currently stopped. Skipping this one" -ForegroundColor Yellow } } else { $vmName = ($vm.resourceid -split '\/')[-1] Write-Host "Working on $vmName" -ForegroundColor Green $vmStatus = Invoke-AzRestMethod -Path ('{0}?api-version=2019-12-12' -f $vm.resourceid) -Method GET | Select-Object -ExpandProperty Content | ConvertFrom-Json | Select-Object -ExpandProperty properties if ($vmStatus.status -match 'Connected') { $res = Invoke-AzRestMethod -Path ('{0}/providers/Microsoft.Security/serverVulnerabilityAssessments/default?api-Version=2015-06-01-preview' -f $vm.resourceid) -Method PUT if ($res.StatusCode -notmatch '200|202') { Write-Host ($res.Content | ConvertFrom-Json).Error.message -ForegroundColor Red } } else { Write-Host "$vmName is currently stopped. Skipping this one" -ForegroundColor Yellow } } }